0x00 简介

WordPress是一个用PHP编写的免费开源内容管理系统,

由于clean_query函数的校验不当,导致了可能通过插件或主题以某种方式从而触发SQL注入的情况。

这类似于tp爆出的那一堆注入,并不是直接就可以用,而是底层逻辑存在bug,要想触发漏洞还得上层的代码进行调用,调用方式如下

1
new WP_Query($_POST['query_vars'])

影响版本

  • 3.7.37 - 5.8.2

其他

参数存在全局转义

image-20220425182636026

0x01 漏洞分析

存在全局转义,有的地方反转义的,但是绝大部分没有,注入只能从不需要单引号的地方寻找,这里先贴一下此漏洞的调用堆栈

1
2
3
4
5
6
7
8
9
10
11
WP_Query::__construct
WP_Query::query
WP_Query::get_posts
WP_Tax_Query::get_sql
WP_Tax_Query::get_sql_clauses
WP_Tax_Query::get_sql_for_query
WP_Tax_Query::get_sql_for_clause
WP_Tax_Query::clean_query
wpdb::get_col
wpdb::query
wpdb::_do_query

当传入的参数不为空时

调用query方法

image-20220425162844393

对成员变量进行赋值,并调用get_posts方法

image-20220425162941550

这个方法其实基本都是在组装sql语句

存在跟多的子结构,有机会可以看看其他地方是否还存在问题

这次只看之前发现的问题

这里的is_singular默认时false,默认就会进入此分支

image-20220425175344987

进一步调用get_sql_clauses

image-20220425175402899

跟进

image-20220425175441444

继续

image-20220425175550474

在clean_query中需要taxonomy参数为空

image-20220425175701911

然后进入transform_query中

传入的值只要是term_taxonomy_id,就会直接return

image-20220425175816276

传入的注入值就会被拼接

image-20220425175924789

这里会对字段进行判断,id类的就不会加单引号,其他的会加单引号

组装好sql语句之后

进入get_col方法

image-20220425180104190

必须要说明的是箭头标注的方法里面会对数据库的字符集进行判断

我传入gbk的参数,无法将check_current_query设置为false

然后进入query

image-20220425180156583

这里就有一点,上面无法设置false,这里面就会return false

image-20220425180345647

最后会进入_do_query方法进行查询

image-20220425180431658

0x02 漏洞复现

在admin-ajax.php中添加如下代码

image-20220425180556498

构造payload

1
action=aa&query_vars[tax_query][1][include_children]=1&query_vars[tax_query][1][terms][1]=1) or updatexml(0x7e,concat(1,user()),0x7e)#&query_vars[tax_query][1][field]=term_taxonomy_id

image-20220425180523575

0x03 修复

官方修复如下,只有当字段名为slug和name的时候,才会保留原数据

image-20220425180654662

wp_parse_id_list对参数进行的强转

image-20220425181022241

0x04 end

至于上面提到的slug和name,可以跟一下

image-20220425181807256

但是由于参数被固定,导致我们对term类的成员变量的可控力度很小

image-20220425181919200

只有一个name参数可控,但是在拼接的时候被单引号包裹

image-20220425182053574

由于存在全局转义,所以无法注入